package com.biboheart.adapter.compiler.grammar;

import com.biboheart.adapter.compiler.ast.Node;
import com.biboheart.adapter.compiler.enums.NodeType;
import com.biboheart.adapter.compiler.enums.TokenLevel;
import com.biboheart.adapter.compiler.enums.TokenType;
import com.biboheart.adapter.compiler.token.Token;
import com.biboheart.adapter.compiler.token.TokenGroup;
import com.biboheart.adapter.compiler.utils.TokenUtils;
import com.biboheart.adapter.support.enums.DelimitEnum;

import java.util.*;

public class OperatorExpression implements Expression{
    private final List<Token> tokenList;

    public OperatorExpression(List<Token> tokenList) {
        this.tokenList = tokenList;
    }

    @Override
    public Node parser() {
        if (null == tokenList) {
            return null;
        }
        // 找出最低优先级的符号
        List<TokenGroup> tokenGroupList = TokenUtils.groupToken(tokenList);
        int index = TokenUtils.getLowestLevelIndex(tokenGroupList);
        List<Token> current = tokenGroupList.get(index).getTokenList();
        if (current.isEmpty()) {
            return null;
        }
        List<Token> left = new ArrayList<>();
        List<Token> right = new ArrayList<>();
        int i = 0;
        for (;i < index; i ++) {
            left.addAll(tokenGroupList.get(i).getTokenList());
        }
        for (i = index + 1; i < tokenGroupList.size(); i ++) {
            right.addAll(tokenGroupList.get(i).getTokenList());
        }
        Token token = current.get(0);
        Node node = new Node();
        node.setToken(token);
        node.setExpression(null);
        node.setNodeType(TokenUtils.compareNodeType(token));
        List<Node> children = new ArrayList<>();
        node.setChildren(children);
        if (!left.isEmpty()) {
            Node child = new Node();
            if (left.size() == 1) {
                child.setToken(left.get(0));
                child.setExpression(null);
            } else {
                child.setToken(null);
                child.setExpression(left);
            }
            child.setNodeType(TokenUtils.compareNodeType(left));
            children.add(child);
        }
        if (!right.isEmpty()) {
            Node child = new Node();
            if (right.size() == 1) {
                child.setToken(right.get(0));
                child.setExpression(null);
            } else {
                child.setToken(null);
                child.setExpression(right);
            }
            child.setNodeType(TokenUtils.compareNodeType(right));
            children.add(child);
        }
        return node;
    }

    private NodeType compareNodeType(List<Token> expr) {
        Token token = expr.get(0);
        if (expr.size() > 1 && (TokenType.TOKEN_VARIABLE.equals(token.getType())
                || TokenType.TOKEN_CONSTANT.equals(token.getType())
                || TokenType.TOKEN_STRING.equals(token.getType())
                || TokenType.TOKEN_NUMBER.equals(token.getType())
                || TokenType.TOKEN_NULL.equals(token.getType())
        )) {
            token = expr.get(1);
        }
        NodeType nodeType = null;
        if (TokenType.TOKEN_KEYWORD.equals(token.getType())) {
            nodeType = NodeType.NODE_COMMAND;
        } else if (TokenType.TOKEN_VARIABLE.equals(token.getType())) {
            nodeType = NodeType.NODE_VARIABLE;
        } else if (TokenType.TOKEN_CONSTANT.equals(token.getType())
                || TokenType.TOKEN_STRING.equals(token.getType())
                || TokenType.TOKEN_NUMBER.equals(token.getType())
                || TokenType.TOKEN_NULL.equals(token.getType())
        ) {
            nodeType = NodeType.NODE_CONSTANT;
        } else if (TokenType.TOKEN_LOGICAL.equals(token.getType()) || TokenType.TOKEN_OPERATOR.equals(token.getType())) {
            nodeType = NodeType.NODE_OPERATOR;
        }
        return nodeType;
    }
}
